/*test Davidbrcz*/

#include <iostream>
#include <string>
#include <boost/shared_ptr.hpp>

#define CHECK_FUN(Policy, Member) enum { Policy##Member = sizeof(&Policy::Member) > 0 };

template 
  <
  class SizePolicy, 
  class ClickAwarenessPolicy,
  class TextPolicy,
  class DrawingPolicy
  >
class widget_impl : 
  public SizePolicy,
  public ClickAwarenessPolicy,
  public TextPolicy,
  public DrawingPolicy
{
    /* Par sûreté, on vérifie la présence des fonctions nécessaires
       dans les politiques */
  CHECK_FUN(DrawingPolicy, draw)
  
  public:
  widget_impl(unsigned int width = 800, unsigned int height = 600, const std::string& text = "")
    : TextPolicy(text), SizePolicy(width, height)
  {
  }
  
  void print_size() const
  {
    std::cout << SizePolicy::width << "x" << SizePolicy::height << std::endl;
  }
};

struct NoText { };
struct NonClickAware { };

struct NonResizable
{
  protected:
  unsigned int width;
  unsigned int height;

  public:
  NonResizable(unsigned int w, unsigned int h) : width(w), height(h) { }
};

struct Resizable
{
  protected:
  unsigned int width;
  unsigned int height;

  public:
  Resizable(unsigned int w, unsigned int h) : width(h), height(h) { }
  
  void resize(unsigned int w, unsigned int h)
  {
    width = w;
    height = h;
  }
};

struct ClickAware
{
  void on_click()
  {
    std::cout << "Clicked" << std::endl;
  }
};

struct ReadOnlyText
{
  protected:
  std::string text;

  public:
  ReadOnlyText(const std::string& t) : text(t) { }
  std::string get_text() { return text; }
};

struct EditableText
{
  protected:
  std::string text;
  
  public:
  EditableText(const std::string& t) : text(t) { }
  std::string get_text() { return text; }
  void set_text(const std::string& s) { text = s; }
};

struct RectangularDraw
{
  void draw()
  {
    std::cout << " _________ " << std::endl;
    std::cout << "|         |" << std::endl;
    std::cout << "|_________|" << std::endl;
  }
};

struct SquareDraw
{
  void draw()
  {
    std::cout << " _____ " << std::endl;
    std::cout << "|     |" << std::endl;
    std::cout << "|     |" << std::endl;
    std::cout << "|_____|" << std::endl;
  }
};

int main()
{
  typedef widget_impl <
    NonResizable,
    NonClickAware,
    ReadOnlyText,
    SquareDraw
      > widget_t;
  
  widget_t w(1024, 780, "The best widget of the world"); 
  w.draw();
  std::cout << "Widget's text : " << w.get_text() << std::endl;
  w.print_size();
  // w.set_text("foo"); ne compile par, car ReadOnlyText
  // w.resize(); ne compile pas, car NonResizable
  // w.on_click(); ne compile pas, car NonClickAware

  return 0;
}
